home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / sysext / init / iconcolo.cpt / Source ƒ / IconPatch.asm < prev    next >
Encoding:
Assembly Source File  |  1990-02-08  |  39.3 KB  |  1,438 lines

  1. ;************************************************************************
  2. ;*                                    *
  3. ;*    Icon Colorizer                title:            *
  4. ;*                                    *
  5. ;************************************************************************
  6.  
  7. Include        EquIP.txt        ; includes SysEqu.D
  8. Include        Traps.txt
  9. Include        ToolEqu.d
  10. Include        SysErr.d
  11. Include        PackMacs.txt
  12. Include        MacPlusEqu.txt
  13. Include        FSEqu.d
  14. Include        QuickEqu.d
  15.  
  16. Include        68K-Macros.asm
  17.  
  18. ;************************************************************************
  19. ;*                                    *
  20. ;*    INIT Resource                            *
  21. ;*                                    *
  22. ;************************************************************************
  23.  
  24. RESOURCE  'INIT'  127  'ColorIcons' 80    ; locked, unpurgeable, system heap
  25.  
  26.     SAVE_ALL
  27.     
  28. ; If shift key or mouse button down or non-color Mac, skip it.
  29.     bsr    RunQual
  30.     tst    d0
  31.     bne    InitFail1
  32.  
  33. ; load the main code resource
  34.     clr.l    -(sp)        ; space for result
  35.     move.l    #'PaTc',-(sp)    ; type
  36.     move    #127,-(sp)    ; ID
  37.     _GetResource        ; load it in
  38.     move.l    (sp)+,a3    ; handle to resource
  39.     cmpa.l    #0,a3        ; is the handle NIL?
  40.     beq    InitFail4    ; exit on fail
  41.  
  42.     move.l    a3,-(sp)    ; save handle for _DetachResource
  43.     move.l    (a3),a3        ; get pointer to resource
  44.     jsr    (a3)        ; jump to it to install
  45.     move    d0,d7        ; save result
  46.  
  47.     _DetachResource        ; the code stays around even after our INIT
  48.                 ; file is closed.
  49.  
  50.     tst    d7
  51.     bne    initFail5
  52.     move    #goodIconID,d7    ; show "good" icon
  53.     bsr    plotIcon
  54.  
  55.                 ; check to see if patch has set its memory-full
  56.                 ; flag.
  57.     move    ipMemFull-Install(a3),d0
  58.     tst    d0
  59.     beq    initDone    ; no - exit normally.
  60.  
  61.     move    #ramFullIconID,d7 ; show "Ram Full" icon
  62.     bsr    plotIcon
  63.  
  64. ; Now, we attempt to fix the Ram Full error for next time.
  65. ;
  66.     clr.l    -(sp)        ; space for return value
  67.     move.l    #'sysz',-(sp)    ; type 'sysz'
  68.     clr    -(sp)        ; id = 0
  69.     _GetResource
  70.     move.l    (sp)+,a2    ; gets handle
  71.     move.l    a2,d0        ; test for NIL handle
  72.     tst.l    d0
  73.     beq    @1
  74.     move.l    (a2),a0        ; gets pointer
  75.     move.l    a0,d0        ; test for NIL master pointer
  76.     tst.l    d0
  77.     beq    @1
  78.     
  79.     move.l    ipMemWant-Install(a3),d0    ; Get estimate
  80.     and.l    #$ffffff,d0
  81.     add.l    #SYSZ_EXCESS,d0
  82.     add.l    #CICN_EXTRA,d0
  83.     move.l    d0,(a0)        ; a0 still points to sysz's data
  84.  
  85.     move.l    a2,-(sp)
  86.     _ChangedResource
  87.     
  88.     clr    -(sp)
  89.     _ResError
  90.     move    (sp)+,d0
  91.     tst    d0
  92.     bne    @1
  93.     
  94.     move.l    a2,-(sp)
  95.     _WriteResource
  96. @1:
  97.     bra    initDone
  98.  
  99. InitFail1:
  100.     bra    InitFail
  101.  
  102. InitFail4:
  103.     move    #Error4ID,d6
  104.     bra    InitFail
  105.  
  106. InitFail5:
  107.     move    ipError-Install(a3),d6    ; Get error code from install code
  108.     bra    InitFail
  109.  
  110. InitFail
  111.     move    #badIconID,d7    ; show "not installed" icon
  112.     bsr    plotIcon
  113.     
  114.     move    d6,d7
  115.     bsr    plotIcon
  116.  
  117. initDone:
  118.     RESTORE_ALL
  119.     rts            ; all done
  120.  
  121. ;
  122. ; Subroutine to figure out if shift key or mouse button is down.
  123. ;
  124. ; Out:
  125. ;    d0    Zero unless error
  126. ;    d6    Contains error Icon ID #
  127. ;
  128. myKeyMap    equ    -16
  129.  
  130. RunQual:
  131.     link    a6,#myKeyMap
  132.  
  133.     tst    ROM85
  134.     blt    rqRtn1
  135.  
  136.     btst.b    #6,ROM85        ; has color quickdraw?
  137.     bne    rqRtn2            ; no - blow it off.
  138.  
  139.     subq    #2,sp
  140.     _Button            
  141.     tst.b    (sp)+
  142.     bne.s    rqRtn3
  143.  
  144.     pea    myKeyMap(a6)
  145.     _GetKeys
  146.  
  147.     btst    #0,myKeyMap+7(a6)    ; test 56th bit in the keymap
  148.     bne.s    rqRtn3            ; (which is the shift key)
  149.  
  150.     moveq    #0,d0
  151.     bra.s    rqBack
  152. rqRtn1:
  153.     move    #Error1ID,d6
  154.     bra    rqerr
  155. rqRtn2:
  156.     move    #Error2ID,d6
  157.     bra    rqerr
  158. rqRtn3:
  159.     move    #Error3ID,d6
  160.     bra    rqerr
  161. rqerr:
  162.     moveq    #1,d0
  163. rqBack:
  164.     unlk    a6
  165.     rts
  166.  
  167.  
  168. ; subroutine to plot our ICN# on the screen.
  169. ;
  170. ; in:
  171. ;    d7.w    icon ID number
  172. ; out:
  173. ;    all registers unchanged
  174. ;
  175. ; This subroutine loads in a CODE resource containing the ShowINIT procedure,
  176. ; whose interface is as follows:
  177. ;
  178. ; PROCEDURE ShowINIT(iconID: Integer; moveX: Integer); EXTERNAL
  179. ;
  180. plotIcon:
  181.     SAVE_ALL
  182.  
  183.     clr.l    -(sp)
  184.     move.l    #'PROC',-(sp)    ; resource type
  185.     move    #showInitID,-(sp)
  186.     _GetResource
  187.     move.l    (sp)+,a3    ; get handle to ShowInit routine
  188.     move.l    a3,d0        ; NIL means GetResource failed
  189.     tst.l    d0
  190.     beq    piGiveUp
  191.  
  192.     move.l    (a3),a3        ; get pointer to ShowInit routine
  193.     move.l    a3,d0        ; NIL means it's been purged!
  194.     tst.l    d0
  195.     beq    piGiveUp
  196.  
  197.     move    d7,-(sp)    ; icon ID
  198.     move    #-1,-(sp)    ; moveX
  199.     jsr    (a3)        ; call ShowInit routine
  200.  
  201.     move.l    a3,-(sp)    ; Now, get rid of the code resource.
  202.     _ReleaseResource
  203.  
  204. piGiveUp:
  205.  
  206.     RESTORE_ALL
  207.     rts
  208.  
  209. ;====================================================================
  210. ;  This is the end of the INIT resource
  211. ;====================================================================
  212.  
  213. RESOURCE  'PaTc' 127 'ColorIcons'  80    ; Starts out locked, unpurgeable,
  214.                     ; system heap
  215.  
  216. ;************************************************************************
  217. ;*                                    *
  218. ;*    'PaTc' Resource                            *
  219. ;*    Installation Code                        *
  220. ;*                                    *
  221. ;************************************************************************
  222.  
  223. Install:
  224.     bra    Install1
  225.     
  226. ipMemFull:    dc.w 0    ; Flag indicating if icons have filled
  227.             ; the buffer yet.
  228.  
  229. ipError:    dc.w 0    ; Error code return to caller
  230.  
  231. ipMemWant:    dc.l 0    ; This is how much memory we "wished we had"
  232.  
  233. LABEL 'Install'
  234. Install1:
  235.     movem.l    a0-a5/d1-d6,-(sp)
  236.  
  237. ; Allocate local storage pointer.
  238.     move.l    #mySize,d0
  239.     _NewPtr,SYS+CLEAR
  240.     tst    d0
  241.     bne    installBad6
  242.     move.l    a0,d0
  243.     tst.l    d0
  244.     beq    installBad6
  245.     lea    a4Save(pc),a1
  246.     move.l    a0,(a1)
  247.  
  248. ; Set up a4.
  249.     move.l    a0,a4
  250.  
  251. ; Allocate scratch cicn space
  252.     move.l    #MAX_CICN,d0
  253.     _NewHandle,SYS+CLEAR
  254.     tst    d0
  255.     bne    installBad6
  256.     move.l    a0,d0
  257.     tst.l    d0
  258.     beq    installBad6
  259.     lea    scratchCicn(a4),a1    ; save the handle
  260.     move.l    a0,(a1)
  261.  
  262. ; Allocate scratch ctab space
  263.     move.l    #MAX_CTAB,d0
  264.     _NewHandle,SYS+CLEAR
  265.     tst    d0
  266.     bne    installBad6
  267.     move.l    a0,d0
  268.     tst.l    d0
  269.     beq    installBad6
  270.     lea    scratchCtab(a4),a1    ; save the handle
  271.     move.l    a0,(a1)
  272.  
  273. ; Allocate scratch cicn image space
  274.     move.l    #MAX_IMAGE,d0
  275.     _NewHandle,SYS+CLEAR
  276.     tst    d0
  277.     bne    installBad6
  278.     move.l    a0,d0
  279.     tst.l    d0
  280.     beq    installBad6
  281.     lea    scratchImage(a4),a1    ; save the handle
  282.     move.l    a0,(a1)
  283.  
  284. ; Allocate space to store icons.  First get 'sysz' resource to find out
  285. ; how much we should allocate.
  286. ;
  287.     clr.l    -(sp)        ; space for return value
  288.     move.l    #'sysz',-(sp)    ; type 'sysz'
  289.     clr    -(sp)        ; id = 0
  290.     _GetResource
  291.     move.l    (sp)+,a0    ; gets handle
  292.     move.l    a0,d0        ; test for NIL handle
  293.     tst.l    d0
  294.     beq    installBad7
  295.     move.l    (a0),a0        ; gets pointer
  296.     move.l    a0,d0        ; test for NIL master pointer
  297.     tst.l    d0
  298.     beq    installBad7
  299.     
  300.     move.l    (a0),d0        ; gets size
  301.     sub.l    #SYSZ_EXCESS,d0
  302.     ble    installBad8    ; test for less than zero left
  303.     move.l    d0,d7        ; save for later
  304.  
  305.     _NewPtr,SYS+CLEAR    ; allocate it
  306.     tst    d0
  307.     bne    installBad9
  308.     move.l    a0,d0
  309.     tst.l    d0
  310.     beq    installBad9
  311.  
  312. ; Initialize linked-list of icons.
  313.     lea    HeadPointer(a4),a1    ; Set head pointer.
  314.     move.l    a0,(a1)
  315.  
  316.     clr.l    (a0)            ; Set "next" pointer of first icon.
  317.  
  318.     lea    TailPointer(a4),a1    ; Init tail pointer.
  319.     move.l    a0,(a1)
  320.     
  321.     add.l    d7,a0            ; init ptr to end of storage
  322.     lea    EndOfStorage(a4),a1
  323.     move.l    a0,(a1)
  324.  
  325. ; Install patches
  326.     bsr    PInstall
  327.  
  328. ; Do a GetResource on all ICN#'s in the current resource file.  This makes the
  329. ; patch load in color icons from the INIT file, thereby letting people define
  330. ; color icon aliases without modifying other files.
  331.     clr    -(sp)
  332.     move.l    #'ICN#',-(sp)
  333.     dc.w    $A80D    ; _Count1Resources
  334.     move    (sp)+,d7        ; number of resources in d7
  335.  
  336. loadIconLoop:
  337.     tst    d7        ; any more icons?
  338.     ble    installOK    ; no - quit.
  339.  
  340.     clr.l    -(sp)
  341.     move.l    #'ICN#',-(sp)
  342.     move    d7,-(sp)
  343.     dc.w    $A80E    ; _Get1IxResource
  344.     move.l    (sp)+,a0
  345.  
  346.     move.l    a0,d0        ; test for errors
  347.     tst.l    d0
  348.     beq    liNext
  349.     tst.l    (a0)
  350.     beq    liNext
  351.     
  352.     move.l    a0,-(sp)    ; resource handle
  353.     pea    scratchID(a4)
  354.     pea    scratchType(a4)
  355.     pea    scratchName(a4)
  356.     _GetResInfo        ; find out ID
  357.     
  358.     clr.l    -(sp)        ; now get the resource again, accessing it
  359.                 ; by its ID.
  360.     move.l    #'ICN#',-(sp)
  361.     move    scratchID(a4),-(sp)
  362.     _GetResource
  363.     move.l    (sp)+,a0
  364.  
  365.     move.l    a0,-(sp)    ; release the resource
  366.     _ReleaseResource
  367.  
  368. liNext:    subq    #1,d7
  369.     bra    loadIconLoop
  370.  
  371. installOK:
  372.     moveq    #0,d0
  373.  
  374. installDone:
  375.     tst.w    d0
  376.     movem.l    (sp)+,a0-a5/d1-d6
  377.     rts
  378.  
  379. installBad6:
  380.     lea    ipError(pc),a0        ; Indicate Error 6 to INIT code.
  381.     move    #Error6ID,(a0)
  382.     bra    installErr
  383.  
  384. installBad7:
  385.     lea    ipError(pc),a0        ; Indicate Error 7 to INIT code.
  386.     move    #Error7ID,(a0)
  387.     bra    installErr
  388.  
  389. installBad8:
  390.     lea    ipError(pc),a0        ; Indicate Error 8 to INIT code.
  391.     move    #Error8ID,(a0)
  392.     bra    installErr
  393.  
  394. installBad9:
  395.     lea    ipError(pc),a0        ; Indicate Error 9 to INIT code.
  396.     move    #Error9ID,(a0)
  397.  
  398. installErr:
  399.     moveq    #-1,d0
  400.     bra    installDone
  401.  
  402. ; end of install.asm
  403.  
  404.  
  405. .align    2
  406.  
  407. a4Save        dc.l    0    ; place to save value of A4 for our local
  408.                 ; storage.
  409.  
  410. PGRSave        dc.l    0    ; trap address for GetResource before we
  411.                 ; patched it.
  412. PPISave        dc.l    0    ; trap address of PlotIcon before we patched
  413.                 ; it.
  414. PCBSave        dc.l    0    ; trap address of CopyBits before we patched
  415.                 ; it.
  416.  
  417. ;************************************************************************
  418. ;*                                    *
  419. ;*    Patches                                *
  420. ;*                                    *
  421. ;************************************************************************
  422.  
  423. PLocals        dc.l    0    ; save locals
  424.  
  425. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  426. ;
  427. ; [P.Install] - install the trap patches.
  428. ;
  429. ; In:    a4 -> tape cache local storage
  430. ;
  431. ; Out:    all registers unchanged
  432. ;    GetResource    - patched
  433. ;    PlotIcon    - patched
  434. ;    CopyBits    - patched
  435. ;    PGRSave(pc)    - gets old trap address
  436. ;    PPISave(pc)    - gets old trap address
  437. ;    PCBSave(pc)    - gets old trap address
  438. ;    PLocals(pc)    - gets a4 for future use
  439. ;
  440. ; Notes:
  441. ; 1)  GetIcon doesn't have to be patched because it calls GetResource.
  442. ;
  443. ; 2)  Patching both PlotIcon and CopyBits is redundant, but since the patch
  444. ; to PlotIcon is cleaner, it is desirable to have both installed.
  445. ;
  446. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  447. LABEL 'PInstall'
  448. PInstall:
  449.     SAVE_ALL
  450.  
  451. ; set up a4
  452.     move.l    a4save(pc),a4
  453.  
  454. ; patch the GetResource trap
  455.     move    #GRTrap,d0
  456.     _GetTrapAddress
  457.     lea    PGRSave(pc),a1
  458.     move.l    a0,(a1)        ; save old address
  459.     move    #GRTrap,d0
  460.     lea    PGetResource(pc),a0
  461.     _SetTrapAddress
  462.  
  463. ; patch the PlotIcon trap
  464.     move    #PITrap,d0
  465.     _GetTrapAddress
  466.     lea    PPISave(pc),a1
  467.     move.l    a0,(a1)        ; save old address
  468.     move    #PITrap,d0
  469.     lea    PPlotIcon(pc),a0
  470.     _SetTrapAddress
  471.  
  472. ; patch the CopyBits trap
  473.     move    #CBTrap,d0
  474.     _GetTrapAddress
  475.     lea    PCBSave(pc),a1
  476.     move.l    a0,(a1)        ; save old address
  477.     move    #CBTrap,d0
  478.     lea    PCopyBits(pc),a0
  479.     _SetTrapAddress
  480.  
  481.     RESTORE_ALL
  482.     rts
  483.  
  484. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  485. ;
  486. ; P.Get.Resource        - Patch to GetResource
  487. ;
  488. ;   This patch intercepts GetResource calls.  It works in the following manner:
  489. ;
  490. ; if (type is not ICN#)
  491. ;    dispatch
  492. ; save parameters;
  493. ; call original GetResource to load in the corresponding 'cicn'
  494. ; if error
  495. ;    restore parameters
  496. ;    dispatch
  497. ; save 'cicn' in our icon-storage area
  498. ; if not enough room left in our storage area
  499. ;    restore parameters
  500. ;    dispatch
  501. ; restore parameters
  502. ; get return address from stack
  503. ; call original GetResource to get the actual icon
  504. ; if it didn't succeed
  505. ;    place return value on stack
  506. ;    return to original return address
  507. ; search for this ICN# - if already in our table, then
  508. ;    place return value on stack
  509. ;    return to original return address
  510. ; save ICN# in our storage area
  511. ; update next and tail pointers
  512. ; place return value on stack
  513. ; return to original return address
  514. ;
  515. ;  The stack for a GetResource call looks like this:
  516. ;
  517. ;                A6        4(A6)       8(A6) 10(A6)      14(A6)
  518. ;                |           |           |     |           |
  519. ; Stack grows --+-----------+-----------+-----+-----------+-----------+---
  520. ; <-- this way  |  Old  A6  | Rtrn Adrs |  ID |  ResType  | Rtrn Value|
  521. ;             --+-----------+-----------+-----+-----------+-----------+---
  522. ;
  523. ; Note:
  524. ;    We go out of our way to make sure that the 'cicn' GetResource call is
  525. ; done before the 'ICN#' GetResource call.  This is to try and make sure that
  526. ; the value of ResError makes sense to the application.
  527. ;
  528. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  529. PGetResource:
  530.     link    a6,#0
  531.     
  532. ; if (type is not ICN#), dispatch
  533.     compare_l 10(a6),#'ICN#'
  534.     bne    PGRQuickExit
  535.  
  536. ; Setup a4
  537.     movem.l    d0-d7/a0-a4,-(sp)
  538.     move.l    a4save(pc),a4
  539.  
  540. ; save parameters
  541.     move    8(a6), ResID(a4)
  542.     move.l    10(a6), ResType(a4)
  543.  
  544. ; call original GetResource to load in the corresponding 'cicn'
  545.     clr.l    -(sp)        ; space for return
  546.     move.l    #'cicn',-(sp)
  547.     move    ResID(a4),-(sp)
  548.     move.l    PGRSave(pc),a0
  549.     jsr    (a0)
  550.     move.l    (sp)+,a0    ; get handle
  551.  
  552. ; if error
  553. ;    restore parameters
  554. ;    dispatch
  555.     move.l    a0,d0
  556.     tst.l    d0
  557.     beq    PGRErr1        ; NIL handle
  558.     tst.l    (a0)
  559.     beq    PGRErr1        ; Handle points to NIL pointer
  560.  
  561.     move.l    a0,cicnHandle(a4)    ; Save it for later when we have to
  562.                     ; do a ReleaseResource on it.
  563.  
  564. ; At this point we've gotten the resource, so it looks like we'll load
  565. ; both it and the ICN# and add 'em to our internal table.  So, we get the
  566. ; handle size (something we need to know anyway) and add it, plus
  567. ; CICN_OFFSET to our estimate of how much memory we'd "like" to have.
  568. ;
  569.     _GetHandleSize
  570.     lea    ipMemWant(pc),a0    ; Add cicn size + CICN_OFFSET to estimate
  571.     add.l    d0,(a0)
  572.     add.l    #CICN_OFFSET,(a0)
  573.     tst.l    d0            ; Now test for error...
  574.     beq    PGRErr1b        ; GetHandleSize returned error
  575.  
  576. ; if not enough room left in our storage area, dispatch
  577. ;
  578.     move.l    d0,cicnSize(a4)        ; save this for later.
  579.     
  580.     move.l    TailPointer(a4),a2    ; get current tail pointer
  581.     adda.l    d0,a2            ; add length of 'cicn'
  582.     adda.l    #CICN_OFFSET,a2        ; and length of other data
  583.     adda.l    #PS_PADDING,a2        ; fudge to be safe
  584.     move.l    EndOfStorage(a4),a3
  585.     compare_l a2,a3
  586.     bge    PGRErr1b        ; not enough room -- blow it off!
  587.  
  588. ; save "cicn" in our icon-storage area
  589. ;
  590.     move.l    cicnHandle(a4),a0    ; get handle to 'cicn' again
  591.     move.l    (a0),a0            ; get pointer to color icon
  592.     move.l    TailPointer(a4),a1    ; Get tail pointer in a1
  593.     adda.l    #CICN_OFFSET,a1        ; offset for 'cicn'
  594.     ;                ; length still in d0
  595.     _BlockMove
  596.     tst    d0
  597.     bne    PGRErr1b
  598.  
  599. ; call original GetResource to get the actual icon
  600. ;
  601.     clr.l    -(sp)            ; space for return
  602.     move.l    ResType(a4),-(sp)
  603.     move    ResID(a4),-(sp)
  604.     move.l    PGRSave(pc),a0
  605.     jsr    (a0)
  606.     move.l    (sp)+,a0    ; get handle
  607.     lea    icnHandle(a4),a1
  608.     move.l    a0,(a1)
  609.  
  610.     move.l    a0,d0        ; test for error.
  611.     tst.l    d0
  612.     beq    PGRErr2        ; NIL handle.
  613.     tst.l    (a0)
  614.     beq    PGRErr2        ; Handle points to NIL.
  615.  
  616. ; search for this ICN# - if already in our table, then
  617. ;    place return value on stack
  618. ;    return to original return address
  619.     clr.l    -(sp)        ; space for return value
  620.     move.l    (a0),a0        ; get 'ICN#' pointer
  621.     move.l    a0,-(sp)    ; push it
  622.     bsr    PGRLookup    ; search
  623.     move.l    (sp)+,a0    ; get result
  624.     move.l    a0,d0        ; check for NIL
  625.     tst.l    d0
  626.     bne    PGRErr2        ; already in table -- return right away.
  627.  
  628. ; save ICN# in our storage area
  629.     move.l    icnHandle(a4),a0    ; get 'ICN#' handle back
  630.     move.l    (a0),a0            ; get pointer
  631.     move.l    TailPointer(a4),a1
  632.     adda.l    #ICN_OFFSET,a1
  633.     move.l    #ICN_LENGTH,d0
  634.     _BlockMove
  635.     tst    d0
  636.     bne    PGRErr2
  637.  
  638. ; update next and tail pointers
  639.     move.l    TailPointer(a4),a1
  640.     move.l    a1,a2
  641.     adda.l    #CICN_OFFSET,a2        ; add length of pointer and 'ICN#'
  642.     move.l    cicnSize(a4),d0
  643.     addq.l    #1,d0            ; round up to an even number (if
  644.     and.l    #$fffffffe,d0        ;   necessary)
  645.     adda.l    d0,a2            ; add length of 'cicn'
  646.     
  647.     move.l    a2,(a1)            ; fill in next field of the record
  648.                     ; we just created.
  649.     move.l    a2,TailPointer(a4)    ; this is the new tailpointer.
  650.     clr.l    (a2)            ; NIL out the next record's next field.
  651.  
  652. ; We have to to return to the caller without dispatching through GetResource.
  653. ; We do this by copying the return address to a different place on the stack
  654. ; and offsetting the SP by +6 to discard the unwanted parameters.
  655. ;
  656. PGRErr2:
  657.     move.l    cicnHandle(a4),-(sp)    ; Release the 'cicn' we loaded.
  658.     _ReleaseResource
  659.     move.l    icnHandle(a4),14(a6)    ; Place return value on stack in
  660.                     ; correct place.
  661.     move.l    4(a6),10(a6)    ; copy their return address to a position right
  662.                 ; below this return value.
  663.     movem.l    (sp)+,d0-d7/a0-a4 ; restore regs
  664.     unlk    a6        ; restore a6
  665.     lea    6(sp),sp    ; discard 6 bytes worth of stack (corresponds
  666.                 ; to the 6 bytes of parameters that our
  667.                 ; original call had.)
  668.     rts            ; return to original return address, leaving
  669.                 ; return value in place.
  670.  
  671.  
  672. ; These three exit points dispatch to the original GetResource by pushing the
  673. ; trap's original address onto the stack and doing an RTS.  This makes the
  674. ; PC jump to the beginning of the original patch with all of the parameters,
  675. ; etc. set up just the way they were when we were called.
  676. ;
  677. PGRQuickExit:
  678.     unlk    a6
  679.     move.l    PGRSave, -(sp)
  680.     rts
  681.  
  682. PGRErr1b:
  683.     move.l    cicnHandle(a4),-(sp)    ; Release the 'cicn' we loaded.
  684.     _ReleaseResource
  685.  
  686.     lea    ipMemFull(pc),a0    ; Set ram-full flag so install code
  687.     move    #1,(a0)            ; can see it.
  688. PGRErr1:
  689.     movem.l    (sp)+,d0-d7/a0-a4
  690.     unlk    a6
  691.     move.l    PGRSave, -(sp)
  692.     rts
  693.  
  694. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  695. ;
  696. ;  PGRL.Lookup        - Find ICON (if present) in our table
  697. ;
  698. ;    This routine looks through our icon storage record for the given icon; if
  699. ; a match is found it returns a pointer to the ICON/cicn record.  Otherwise
  700. ; returns NIL.
  701. ;
  702. ;    It is stack-based; its prototype is:
  703. ;
  704. ; pascal longword PGRLLookup(Pointer ih);
  705. ;
  706. PGRLookUp:
  707.     STACK_DECLARE
  708.     LONG_PARAM    ih    ; handle to ICON
  709.     STACK_BEGIN
  710.     
  711.     SAVE_ALL
  712.     
  713.     clr.l    d0        ; clear return value for starters.
  714.     move.l    d0,(a6)
  715.     
  716.     move.l    a4save,a4
  717.     
  718.     move.l    HeadPointer(a4),a2    ; points to first ICON/cicn record
  719.  
  720. PGRLTry:
  721.     move.l    (a2),d0        ; test current record's next pointer: is it
  722.     tst.l    d0        ; NIL?
  723.     beq    PGRLDone    ; ...then this record is unused and there are
  724.                 ; no more icons.
  725.     
  726.     move.l    parm_ih(a6),a3    ; get pointer to ICON
  727.  
  728.     lea    ICN_OFFSET(a2),a1    ; points to ICON
  729.     move    #(ICN_LENGTH/4)-1,d7
  730. @1:    compare_l (a1)+, (a3)+    ; compare 4 icon bytes
  731.     bne    PGRLTryNext    ; differ!  This icon is not a match.
  732.     dbf    d7,@1        ; loop back and try next longword.
  733.  
  734. PGRLFound:
  735.     move.l    a2,(a6)        ; return pointer to ICON/cicn record.
  736.     bra    PGRLDone
  737.  
  738. PGRLTryNext:
  739.     move.l    (a2),a2        ; go to next ICON/cicn record.
  740.     bra    PGRLTry        ; loop back to test it.
  741.  
  742. PGRLDone:
  743.     RESTORE_ALL
  744.     STACK_END
  745.  
  746. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  747. ;
  748. ; P.Plot.Icon        - Patch to PlotIcon
  749. ;
  750. ;   This patch intercepts PlotIcon calls.  It works in the following manner:
  751. ;
  752. ; call GetPort and check the rowbytes, # of bits, etc.
  753. ; if rowBytes has high 3 bits clear, then
  754. ;    dispatch
  755. ; if # of bits is less than 4
  756. ;    dispatch
  757. ;
  758. ; search for ICN# in our table
  759. ; if not found
  760. ;    dispatch
  761. ; call PlotCIcon 
  762. ;
  763. ;  The stack for a PlotIcon call looks like this:
  764. ;
  765. ;                A6        4(A6)       8(A6)       12(A6)
  766. ;                |           |           |           |
  767. ; Stack grows --+-----------+-----------+-----------+-----------+---
  768. ; <-- this way  |  Old  A6  | Rtrn Adrs |  Icon Hdl |  Rect Ptr |
  769. ;             --+-----------+-----------+-----------+-----------+---
  770. ;
  771. ; Notes:
  772. ; 1)  This patch has a known bug: it passes a "fake handle" to PlotCIcon.  This
  773. ; bug can be fixed (if necessary) by having the install code allocate a handle,
  774. ; then have this patch copy the cicn data into this "scratch buffer" and pass
  775. ; the handle to the scratch buffer to PlotCIcon.
  776. ;
  777. ; 2)  The GetPort checking is currently not done.  This means that the patch
  778. ; will still be acting if the monitor is set to 1 or 2 bits.  Since PlotIcon
  779. ; uses the B/W icon automatically in this case, it's not really a problem --
  780. ; it just makes drawing a bit slower because of the overhead of this code.
  781. ;
  782. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  783. PPlotIcon:
  784.     link    a6,#0
  785.     movem.l    d0-d7/a0-a4,-(sp)
  786.     
  787.     move.l    a4save(pc),a4
  788.  
  789.     clr.l    -(sp)        ; space for return value
  790.     move.l    8(a6),a0    ; ICN# handle
  791.     move.l    (a0),-(sp)    ; push pointer
  792.     bsr    PGRLookup
  793.     move.l    (sp)+,a0    ; get result
  794.     move.l    a0,d0        ; is it NIL?
  795.     tst.l    d0
  796.     beq    PPIErr1        ; yep, no color icon, so dispatch.
  797.  
  798.     adda.l    #CICN_OFFSET,a0    ; get ptr to cicn
  799.     move.l    12(a6),-(sp)    ; use the rect ptr that they gave us
  800.     move.l    a0,-(sp)    ; pointer to cicn resource structure
  801.     clr    -(sp)        ; SrcCopy mode
  802.     bsr    PCBPlotIt
  803.     
  804. ; Exit point for returning without dispatching.
  805. ;
  806. PPIErr2:
  807.     move.l    4(a6),12(a6)    ; copy their return address to top 4 bytes of
  808.                 ; original parameters.
  809.     movem.l    (sp)+,d0-d7/a0-a4 ; restore regs
  810.     unlk    a6        ; restore a6
  811.     lea    8(sp),sp    ; discard 8 bytes worth of stack (corresponds
  812.                 ; to the 8 bytes of parameters that our
  813.                 ; original call had.)
  814.     rts            ; return to original return address.
  815.  
  816. ; Exit point for dispatching to PlotIcon
  817. ;
  818. PPIErr1:
  819.     movem.l    (sp)+,d0-d7/a0-a4
  820.     unlk    a6
  821.     move.l    PPISave, -(sp)
  822.     rts
  823.     
  824.  
  825. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  826. ;
  827. ; P.CopyBits        - Patch to CopyBits
  828. ;
  829. ;   This patch intercepts CopyBits calls.  It works in the following manner:
  830. ;
  831. ; call GetPort and check the rowbytes, # of bits, etc.
  832. ; if rowBytes has high 3 bits clear, then
  833. ;    dispatch
  834. ; if # of bits is less than 4
  835. ;    dispatch
  836. ;
  837. ; if MaskRgn not NIL then dispatch
  838. ; if mode == srcBic or mode == notSrcBic then dispatch
  839. ; if srcRect not equal to (0,0,32,32) then dispatch
  840. ; if srcBits rowBytes not equal to 4 then dispatch
  841. ; if srcBits bounds not equal to (0,0,32,32) then dispatch
  842. ; search for ICN# in our table
  843. ; if not found
  844. ;    dispatch
  845. ; call PlotCIcon 
  846. ;
  847. ;  The stack for a CopyBits call looks like this:
  848. ;
  849. ;                A6      4(A6)     8(A6)    12(A6) 14(a6)
  850. ;                |         |         |         |    |
  851. ; Stack grows --+---------+---------+---------+----+---------+-/
  852. ; <-- this way  | Old  A6 |Rtrn Adrs| maskRgn |mode| dstRect | \
  853. ;             --+---------+---------+---------+----+---------+-/
  854. ;
  855. ;                     18(a6)    22(a6)    26(a6)
  856. ;                       |         |         |
  857. ;                    /-+---------+---------+---------+---
  858. ;                    \ | srcRect | dstBits | srcBits |
  859. ;                    /-+---------+---------+---------+---
  860. ;
  861. ; Notes:
  862. ; 1)  See note 1) in PPlotIcon above.
  863. ;
  864. ; 2)  See note 2) in PPlotIcon above.
  865. ;
  866. ; 3)  CopyBits must be patched to get color icons in the Finder.  Apparently,
  867. ; the Finder uses CopyBits instead of PlotIcon for two reasons:
  868. ;    1.    They occasionally have to create their own off-screen bitmap for the
  869. ;    purposes of (among other things) creating dimmed icons and creating
  870. ;    the gray outline of the mask for dragging icons.
  871. ;    2. PlotIcon calls are ignored when printing.  In other words, they are not
  872. ;    caught by the bottleneck proc that captures picture data between
  873. ;    PrOpenPage and PrClosePage.
  874. ;
  875. ; 4)  There are certain situations in which this patch will get fooled by a
  876. ; CopyBits call that is not really an icon.  This will happen, for example, if
  877. ; (in MacPaint) you select an area exactly 32x32 pixels in size which contains
  878. ; an image exactly identical to that in one of our icons and drag it with the
  879. ; mouse.  Since such an occurrance is rare (except when done deliberately) I
  880. ; deem the bug acceptable.
  881. ;     In fact, I couldn't even duplicate the bug deliberately, although I
  882. ; tried in several popular applications.
  883. ;     We could fix this bug by checking the current application name (to see if
  884. ; it's the Finder) but this would not work under MultiFinder.
  885. ;
  886. ; 5)  There is a potential problem with printing.  This patch replaces CopyBits
  887. ; calls with PlotCIcon calls.  Because PlotCIcon calls are ignored by the Print
  888. ; Manager, they will not show up in the printed output.  This is not a problem
  889. ; with black-and-white printers like the 5.0 LaserWriter because we check the
  890. ; color QuickDraw flags of dstBits, which are clear when printing to a black-
  891. ; and-white printer.  However, with 6.0 LaserWriters it doesn't work, because
  892. ; the printing port is a CGrafPort.
  893. ;
  894. ; 6)  We currently plot in color whenever the bits-per-pixel is greater than
  895. ; one.  This generates somewhat crummy results on monitors set to 2 bits
  896. ; per pixel (four colors), although for most color icons, the results are
  897. ; always better than the 1-bit-per-pixel alternatives.
  898. ;     Thus, I've decided to leave it this way until someone complains about
  899. ; it.
  900. ;
  901. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  902. PCopyBits:
  903.     link    a6,#0
  904.     movem.l    d0-d7/a0-a4,-(sp)
  905.     
  906.     move.l    a4save(pc),a4
  907.  
  908. ; if MaskRgn not NIL then dispatch
  909.     tst.l    8(a6)
  910.     bne    PCBErr1
  911.  
  912. ; if mode == srcBic or mode == notSrcBic then dispatch
  913.     move    12(a6),d0
  914.     compare    d0,#srcBic
  915.     beq    PCBErr1
  916.     compare    d0,#notSrcBic
  917.     beq    PCBErr1
  918.  
  919. ; if srcBits rowBytes not equal to 4 then dispatch
  920.     move.l    26(a6),a0    ; get srcBits
  921.     move    rowBytes(a0),d0    ; get RowBytes
  922.     compare    d0,#4
  923.     bne    PCBErr1
  924.  
  925. ; if dstBits is not a color bitmap, dispatch
  926.     move.l    22(a6),a0    ; get dstBits
  927.     move    rowBytes(a0),d0    ; get RowBytes
  928.     and    #$c000,d0    ; see if it's a portPixMap handle
  929.     compare    d0,#$c000
  930.     beq    PCBCont1    ; it is -- go ahead.
  931.     
  932.     move    rowBytes(a0),d0    ; get RowBytes again
  933.     and    #$e000,d0    ; check for color QD bits
  934.     beq    PCBErr1        ; no color QD bits set - blow it off!
  935.  
  936.     bra.s    PCBCont2
  937.  
  938. PCBCont1:
  939.     move.l    (a0),a0        ; dereference portPixMap handle
  940.     move.l    (a0),a0
  941.     
  942. PCBCont2:    ; a0 now points to destination pixMap
  943.  
  944. ; if dstBits is less than 2 bits per pixel, dispatch.  (See note 6
  945. ; above.)
  946.     move    32(a0),d0    ; get bits-per-pixel
  947.     compare    d0, #2
  948.     blt    PCBErr1
  949.  
  950. ; if srcRect not equal to (0,0,32,32) then dispatch
  951.     move.l    18(a6),a0    ; get srcRect ptr
  952.     move.l    (a0)+,d0    ; get top left
  953.     bne    PCBErr1        ; nonzero - dispatch.
  954.     move.l    (a0),d0        ; get bottom right
  955.     compare_l d0,#$200020    ; compare to (32, 32)
  956.     bne    PCBErr1        ; no - dispatch.
  957.  
  958. ; if srcBits bounds not equal to (0,0,32,32) then dispatch
  959.     move.l    26(a6),a0    ; get srcBits
  960.     lea    bounds(a0),a0
  961.     move.l    (a0)+,d0    ; get top left
  962.     bne    PCBErr1        ; nonzero - dispatch.
  963.     move.l    (a0),d0        ; get bottom right
  964.     compare_l d0,#$200020    ; compare to (32, 32)
  965.     bne    PCBErr1        ; no - dispatch.
  966.  
  967. ; search for ICN# in our table
  968. ; if not found, dispatch
  969. ; call PlotCIcon
  970.     move.l    26(a6),a0    ; get srcBits again
  971.     clr.l    -(sp)        ; space for return value
  972.     move.l    (a0),-(sp)    ; push baseAddr of source bitmap
  973.     bsr    PGRLookup
  974.     move.l    (sp)+,a0    ; get result
  975.     move.l    a0,d0        ; is it NIL?
  976.     tst.l    d0
  977.     beq    PCBErr1        ; yep, no color icon, so dispatch.
  978.     
  979.     adda.l    #CICN_OFFSET,a0    ; get ptr to cicn
  980.     move.l    14(a6),-(sp)    ; use the dstRect that they gave us
  981.     move.l    a0,-(sp)    ; pointer to cicn resource structure
  982.     move    12(a6),-(sp)    ; transfer mode
  983.     bsr    PCBPlotIt
  984.     
  985. ; Exit point for returning without dispatching.
  986. ;
  987. PCBErr2:
  988.     move.l    4(a6),26(a6)    ; copy their return address to top 4 bytes of
  989.                 ; original parameters.
  990.     movem.l    (sp)+,d0-d7/a0-a4 ; restore regs
  991.     unlk    a6        ; restore a6
  992.     lea    22(sp),sp    ; discard 22 bytes worth of stack (corresponds
  993.                 ; to the 22 bytes of parameters that our
  994.                 ; original call had.)
  995.     rts            ; return to original return address.
  996.  
  997. ; Exit point for dispatching to CopyBits
  998. ;
  999. PCBErr1:
  1000.     movem.l    (sp)+,d0-d7/a0-a4
  1001.     unlk    a6
  1002.     move.l    PCBSave, -(sp)
  1003.     rts
  1004.  
  1005. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1006. ;
  1007. ;  PCB.PlotIt    - set up cicn structures and call PlotCIcon
  1008. ;
  1009. ;     This routine takes a pointer to an ICON/cicn record and plots the cicn
  1010. ; on the screen, given a rectangle.  Since the cicn portion of the record is
  1011. ; still in its "raw" cicn resource format, the first steps involve "parsing
  1012. ; out" the fields of the 'cicn' resource data.  This resource structure is
  1013. ; documented in Inside Mac, vol. 5, pages 80-81.
  1014. ;     Here's the pseudo-code for this routine:
  1015. ;
  1016. ; compute icon height in pixels
  1017. ; compute offsets for MaskData and BMapData, and total length of everything
  1018. ;   up to the end of the BMapData
  1019. ; if too long, dispatch
  1020. ; compute offset and length of PMapCTab
  1021. ; if color table too big, dispatch
  1022. ; compute offset and length for cicn image data
  1023. ; if cicn image data too large, dispatch
  1024. ; copy cicn image data into scratch image space
  1025. ; copy color table data into scratch ctab space
  1026. ; copy rest of it into scratch cicn space
  1027. ; fill in fields of cicn: cicn BaseAddr, icon PMTable, mask BaseAddr, BMap
  1028. ;   BaseAddr, IconData handle
  1029. ; set foreground and background colors
  1030. ; get dstBits and bounds from current port
  1031. ; call CopyBits
  1032. ;
  1033. ;     This is a stack-based routine:
  1034. ;
  1035. ; pascal void PCBPlotIt(Pointer the_rect, Pointer the_icon, word mode);
  1036. ;
  1037. ; Notes:
  1038. ; 1)  Although this routine handles icons of any pixel-size (not just 32x32),
  1039. ; it assumes that the height of all three icons (B/W icon, mask, and color
  1040. ; icon) is the same.  It could be made more robust by looking at the IconMask
  1041. ; and IconBMap bounds rectangles and treating them seperately.
  1042. ;
  1043. ; 2)  The CopyBits patch that calls us checks specifically for 32x32 icons.
  1044. ; This means that if our 'cicn' is not 32x32, it will only get plotted on
  1045. ; PlotIcon calls.
  1046. ;
  1047. ; 3)  This routine doesn't take the same parameters as CopyBits because it
  1048. ; is called by the PlotIcon patch, which doesn't have all the information
  1049. ; which CopyBits has.  Therefore, this routine has to figure out on its own
  1050. ; what the dstBits should be.
  1051. ;
  1052. ; 4)  In its original implementation, this routine plotted by calling
  1053. ; PlotCIcon.  This required setting up a CIcon record with pointers to
  1054. ; PixMap data, two sets of BitMap data, and a color table.  Now that we
  1055. ; use CopyBits to do the drawing, none of this is needed except for the
  1056. ; PixMap (which is the first portion of the CIcon data structure) and
  1057. ; the color table and pixel image to which it points.  Thus, some code
  1058. ; has been commented out, and some is somewhat superfluous.
  1059. ;
  1060. PCBPlotIt:
  1061.     STACK_DECLARE
  1062.     LONG_PARAM    rectptr
  1063.     LONG_PARAM    cicnptr
  1064.     WORD_PARAM    mode
  1065.     STACK_BEGIN
  1066.     SAVE_ALL
  1067.     
  1068.     move.l    a4save(pc),a4    ; set up a4
  1069.     
  1070. ; compute icon height in pixels (This is used later on in computing data
  1071. ; sizes of bitMaps and pixMaps)
  1072.     move.l    parm_cicnptr(a6),a3    ; set up pointer to the structure
  1073.     move    6+4(a3),d0        ; get PMap bounds bottom
  1074.     sub    6(a3),d0        ; subtract bounds top
  1075.     move    d0,pcbHeight(a4)    ; save it
  1076.  
  1077. ; compute offsets for MaskData and BMapData, and total length of everything
  1078. ;   up to the end of the BMapData
  1079.     ; (offset for MaskData is always 82)
  1080.     move    #82,d0            ; maskdata offset
  1081.     move    54(a3),d1        ; get maskdata rowBytes
  1082.     and    #$1fff,d1        ; mask out color QD bits
  1083.     mulu    pcbHeight(a4),d1    ; multiply by icon height
  1084.     add    d1,d0            ; add this.
  1085.     move    d0,pcbBmapOffset(a4)    ; save offset for use later.
  1086.  
  1087.     move    68(a3),d1        ; get bmap rowBytes
  1088.     and    #$1fff,d1        ; mask out color QD bits
  1089.     mulu    pcbHeight(a4),d1    ; multiply by icon height
  1090.     add    d1,d0            ; add this.
  1091.     move    d0,pcbCicnLength(a4)    ; save length for use later.
  1092.  
  1093. ; if too long, dispatch
  1094.     compare    d0,#MAX_CICN
  1095.     bge    PCBGiveUp
  1096.  
  1097. ; compute offset and length of PMapCTab
  1098.     ; (offset is the same as the length we just computed)
  1099.     move.l    a3,a1            ; get ptr to structure
  1100.     adda    d0,a1            ; point to color table
  1101.     move    6(a1),d0        ; get ctSize
  1102.     addq    #1,d0            ; add 1
  1103.     asl    #3,d0            ; multiply by 8
  1104.     addq    #8,d0            ; add 8 for first three fields
  1105.     move    d0,pcbCtabLength(a4)    ; save it
  1106.     
  1107. ; if color table too big, dispatch
  1108.     compare    d0,#MAX_CTAB
  1109.     bge    PCBGiveUp
  1110.  
  1111. ; compute offset and length for cicn image data
  1112.     move    4(a3),d0        ; get pmap rowbytes
  1113.     and    #$1fff,d0        ; mask out color QD bits
  1114.     mulu    pcbHeight(a4),d0    ; multiply by icon height
  1115.     move    d0,pcbImageLength(a4)    ; save it
  1116.  
  1117. ; if cicn image data too large, dispatch
  1118.     compare    d0,#MAX_IMAGE
  1119.     bge    PCBGiveUp
  1120.  
  1121. ; copy cicn image data into scratch image space
  1122.     move    pcbCicnLength(a4),d0    ; get ctab offset
  1123.     add    pcbCtabLength(a4),d0    ; add ctab size to get image offset
  1124.     move.l    a3,a0            ; pointer to whole structure
  1125.     adda    d0,a0            ; now points to cicn image
  1126.     move    pcbImageLength(a4),d0    ; set up length
  1127.     move.l    scratchImage(a4),a1    ; image space handle
  1128.     move.l    (a1),a1            ; get pointer
  1129.     _BlockMove
  1130.     tst    d0
  1131.     bne    PCBGiveUp
  1132.  
  1133. ; copy color table data into scratch ctab space
  1134.     move    pcbCicnLength(a4),d0    ; get ctab offset
  1135.     move.l    a3,a0
  1136.     adda    d0,a0            ; pointer to ctab
  1137.     move    pcbCTabLength(a4),d0    ; ctab length
  1138.     move.l    scratchCtab(a4),a1    ; handle to scratch ctab
  1139.     move.l    (a1),a1            ; pointer
  1140.     _BlockMove
  1141.     tst    d0
  1142.     bne    PCBGiveUp
  1143.  
  1144. ; copy rest of it into scratch cicn space.  (Note: we don't actually need
  1145. ; all of this, we really only need the first portion, which becomes the
  1146. ; PixMap.  See note 4 above)
  1147.     move.l    a3,a0            ; pointer to main structure
  1148.     move    pcbCicnLength(a4),d0    ; length
  1149.     move.l    scratchCicn(a4),a1
  1150.     move.l    (a1),a1
  1151.     _BlockMove
  1152.     tst    d0
  1153.     bne    PCBGiveUp
  1154.  
  1155. ; fill in fields of cicn: cicn BaseAddr, icon PMTable, mask BaseAddr, BMap
  1156. ;   BaseAddr, IconData handle
  1157.     move.l    scratchCicn(a4),a1    ; get handle to cicn again
  1158.     move.l    (a1),a1            ; get pointer
  1159.     
  1160.     move.l    scratchImage(a4),a0
  1161.     move.l    (a0),a0
  1162.     move.l    a0,(a1)            ; fill in PMap BaseAddr
  1163.     
  1164.     move.l    scratchCTab(a4),a0
  1165.     move.l    a0,42(a1)        ; fill in PMap PMTable
  1166.  
  1167. ; We're setting up the mask's bitmap, solely for use in a CopyMask call.
  1168. ; The CopyBits call to the screen doesn't use the mask.
  1169.     move.l    a1,a0
  1170.     adda    #82,a0            ; points to mask data
  1171.     move.l    a0,50(a1)        ; fill in IconMask baseAddr
  1172.  
  1173. ; These instructions are NOP'ed because they're only necessary for
  1174. ; PlotCIcon, which we no longer use.
  1175. ;
  1176. ;    move.l    a1,a0
  1177. ;    adda    pcbBmapOffset(a4),a0    ; points to BMap
  1178. ;    move.l    a0,64(a1)        ; fill in BMap baseAddr
  1179. ;
  1180. ;    move.l    scratchImage(a4),78(a1)    ; fill in IconData handle
  1181. ;
  1182. ; call PlotCIcon.  The Pascal interface for this is:
  1183. ;       PlotCIcon(r: Rect; icon: cIconHandle);
  1184. ;
  1185. ;    move.l    parm_rectptr(a6),-(sp)    ; rect
  1186. ;    move.l    scratchCicn(a4),-(sp)    ; cicn handle
  1187. ;    dc.w    $AA1F            ; trap word for PlotCIcon
  1188.  
  1189. ; Getting the current port to use the bitmap is fine, however, we shouldn't
  1190. ; try to use the current port to get the current ForeColor.  This won't work
  1191. ; if the current port is an old-style GrafPort.
  1192.     pea    curForeColor(a4)
  1193.     dc.w    $AA19            ; trap word for GetForeColor
  1194.     
  1195.     pea    curBackColor(a4)
  1196.     dc.w    $AA1A            ; trap word for GetBackColor
  1197.     
  1198.     pea    blackRGB(pc)
  1199.     dc.w    $AA14            ; trap word for RGBForeColor
  1200.     
  1201.     pea    whiteRGB(pc)
  1202.     dc.w    $AA15            ; trap word for RGBBackColor
  1203.     
  1204.     pea    grayRGB(pc)        ; %%% Set a gray opColor
  1205.     dc.w    $AA21            ; trap word for OpColor
  1206.  
  1207. ; Now, we determine if "the icon is selected".  This is actually a
  1208. ; determination of what the foreground color is, etc. but in the
  1209. ; Finder this amounts to determining if the icon is selected.
  1210. ;
  1211. ; In the Finder, the ForeColor is white if and only if the icon
  1212. ; is selected.
  1213. ;
  1214. ; Notes:
  1215. ; 1)  We also check the transfer mode to see if it's srcCopy.  This
  1216. ; is a basic check to try to avoid doing Finder-like drawing in
  1217. ; applications other than the Finder.  The Finder seems to always
  1218. ; draw icons in srcOr mode (and masks in srcBic mode).
  1219. ;
  1220.     tst    parm_mode(a6)        ; Transfer mode = SrcCopy?
  1221.     beq    PCBNotSelected        ; NO - don't treat as selected.
  1222.  
  1223.     move.l    curForeColor(a4),d0    ; Test Red and Green
  1224.     not.l    d0            ; are they both FFFF?
  1225.     bne    PCBNotSelected        ; NO - not selected
  1226.     move.w    curForeColor+4(a4),d0    ; Test Blue
  1227.     not.w    d0            ; is it FFFF?
  1228.     bne    PCBNotSelected        ; NO - not selected
  1229.  
  1230.     lea    selected(a4),a0        ; Yup, it's selected.
  1231.     move    #1,(a0)
  1232.     bra    PCBlabel1
  1233.  
  1234. PCBNotSelected:
  1235.     lea    selected(a4),a0
  1236.     clr    (a0)
  1237.     bra    PCBlabel1
  1238.  
  1239. PCBlabel1:
  1240.  
  1241.     move    selected(a4),d0        ; Selected flag TRUE?
  1242.     beq    PCBCopyBits        ; no, use newMul & CopyBits method
  1243.     
  1244. ; =============================================
  1245. ; Selected Icon: Blend Color-table and CopyMask
  1246. ; =============================================
  1247. ; If the icon is *selected*, the Finder draws it with a non-white ForeColor.
  1248. ; in this case, we desire the icon to appear on the screen "blended" with
  1249. ; the selected ForeColor (which the Finder has just drawn in the mask).
  1250. ;     Unfortunately, we can't do the "blend" transfer mode *and* mask the
  1251. ; operation to the icon's mask in a single operation unless we first convert
  1252. ; the icon's mask into a region.
  1253. ;     A multiple-operation approach is possible, but since that involves
  1254. ; creating a third bitmap, we must then worry about the GDevice and
  1255. ; maxGDevice.  Also, of course, it's slower.
  1256. ;     So, instead, we perform the blend by modifying the color table of
  1257. ; the temporary CIcon we've just constructed.  Then, we use CopyMask to
  1258. ; place the appropriate portion of the icon on screen.
  1259. ;
  1260. ; If the icon is selected, the selected icon color is the BackColor.
  1261. ;
  1262.  
  1263. ; Okay, we know we want to blend.  Now, change the color table.
  1264.     moveq.l    #0,d2            ; Get SelColor's red in D2
  1265.     move    curBackColor(a4),d2
  1266.     moveq.l    #0,d3            ; Get SelColor's green in D3
  1267.     move    curBackColor+2(a4),d3
  1268.     moveq.l    #0,d4            ; Get SelColor's blue in D4
  1269.     move    curBackColor+4(a4),d4
  1270.  
  1271.     move.l    scratchCtab(a4),a1    ; get handle to scratch ctab
  1272.     move.l    (a1),a1            ; pointer
  1273.     move    6(a1),d0        ; Get ctSize field
  1274.     lea    10(a1),a1        ; Point a1 at first RGBColor
  1275. @2:
  1276.     moveq.l    #0,d1            ; Get color table's red
  1277.     move    (a1),d1
  1278.     add.l    d2,d1            ; Add "our" red
  1279.     asr.l    #1,d1            ; divide by two
  1280.     move    d1,(a1)            ; write it back
  1281.  
  1282.     moveq.l    #0,d1            ; Get color table's green
  1283.     move    2(a1),d1
  1284.     add.l    d3,d1            ; Add "our" green
  1285.     asr.l    #1,d1            ; divide by two
  1286.     move    d1,2(a1)        ; write it back
  1287.  
  1288.     moveq.l    #0,d1            ; Get color table's blue
  1289.     move    4(a1),d1
  1290.     add.l    d4,d1            ; Add "our" blue
  1291.     asr.l    #1,d1            ; divide by two
  1292.     move    d1,4(a1)        ; write it back
  1293.  
  1294.     lea    8(a1),a1        ; bump pointer
  1295.     dbf    d0,@2            ; and loop.
  1296.  
  1297.  
  1298. ; Now that the color table's been suitably munged, we can go ahead and
  1299. ; do the actual drawing.  We use CopyMask so as to avoid transfer of the
  1300. ; "stuff around the edges".  Since we've changed the color table, this
  1301. ; "stuff" is no longer white, and therefore a transfer operation which
  1302. ; results in no-change for white source pixels is no longer useful.
  1303. ;
  1304. ; Notes:
  1305. ; 1)  Since we're using CopyMask, this drawing won't appear in printed
  1306. ; output.  Thus we would expect any selected icons to not appear in a
  1307. ; PrintCatalog to LaserWriter 6.0.  This doesn't actually appear to
  1308. ; happen, however, perhaps because the Finder doesn't draw the icons
  1309. ; in selected mode when printing.
  1310. ;     Anyway, if the bug ever does actually happen, it can be fixed
  1311. ; easily by always drawing in the "unselected" mode first (using a
  1312. ; CopyBits), and then drawing in this mode.  However, this will slow
  1313. ; down the drawing of selected icons.
  1314. ;
  1315.     move.l    scratchCicn(a4),a1    ; get handle to cicn
  1316.     move.l    (a1),a1            ; get pointer to our pixMap
  1317.     move.l    a1,-(sp)        ; push pointer
  1318.  
  1319.     move.l    scratchCicn(a4),a1    ; get handle to cicn again
  1320.     move.l    (a1),a1            ; get pointer
  1321.     lea    50(a1),a1        ; bump pointer to mask BitMap
  1322.     move.l    a1,-(sp)        ; push mask BitMap address
  1323.  
  1324.     pea    curPort(a4)
  1325.     _GetPort
  1326.     move.l    curPort(a4),a1        ; get pointer to port
  1327.     lea    2(a1), a1        ; pointer to port's bitmap
  1328.     move.l    a1,-(sp)
  1329.  
  1330.     move.l    scratchCicn(a4),a1    ; get handle to cicn
  1331.     move.l    (a1),a1            ; get pointer to cicn
  1332.     pea    6(a1)            ; push pointer to bounds rect
  1333.  
  1334.     pea    56(a1)            ; mask rect pointer %%% not checking size!
  1335.  
  1336.     move.l    parm_rectptr(a6),-(sp)    ; dest rect pointer
  1337.  
  1338.     _CopyMask
  1339.  
  1340.     bra    PCBExit
  1341.  
  1342. ; ================================================
  1343. ; Unselected Icon: NewMul Color-table and CopyBits
  1344. ; ================================================
  1345. PCBCopyBits:
  1346.  
  1347. ; We've determined that the icon is not selected.  In this case, we want to
  1348. ; do a "NewMul" operation on the color table and then CopyBits in transparent
  1349. ; mode.
  1350. ;
  1351. ; NewMul is defined as follows:
  1352. ;    Color = SelColor + Color*(WHITE - SelColor)
  1353. ; This calculation is carried out independently on each of the three components.
  1354. ;
  1355. ; If the icon is unselected, the selected icon color is the ForeColor.
  1356. ;
  1357.     moveq.l    #0,d2            ; Get SelColor's red in D2
  1358.     move    curForeColor(a4),d2
  1359.     moveq.l    #0,d3            ; Get SelColor's green in D3
  1360.     move    curForeColor+2(a4),d3
  1361.     moveq.l    #0,d4            ; Get SelColor's blue in D4
  1362.     move    curForeColor+4(a4),d4
  1363.  
  1364.     move.l    scratchCtab(a4),a1    ; get handle to scratch ctab
  1365.     move.l    (a1),a1            ; pointer
  1366.     move    6(a1),d0        ; Get ctSize field
  1367.     lea    10(a1),a1        ; Point a1 at first RGBColor
  1368. @2:
  1369.     moveq.l    #0,d1            ; Get color table's red
  1370.     move    (a1),d1
  1371.     not    d2            ; Subtract the SelColor from FFFF
  1372.     mulu    d2,d1            ; Multiply by color
  1373.     swap    d1
  1374.     not    d2            ; Restore original SelColor
  1375.     add    d2,d1            ; And add it to the product.
  1376.     move    d1,(a1)            ; write it back
  1377.  
  1378.     moveq.l    #0,d1            ; Get color table's green
  1379.     move    2(a1),d1
  1380.     not    d3            ; Same calculation
  1381.     mulu    d3,d1
  1382.     swap    d1
  1383.     not    d3
  1384.     add    d3,d1
  1385.     move    d1,2(a1)        ; write it back
  1386.  
  1387.     moveq.l    #0,d1            ; Get color table's blue
  1388.     move    4(a1),d1
  1389.     not    d4            ; Same calculation
  1390.     mulu    d4,d1
  1391.     swap    d1
  1392.     not    d4
  1393.     add    d4,d1
  1394.     move    d1,4(a1)        ; write it back
  1395.  
  1396.     lea    8(a1),a1        ; bump pointer
  1397.     dbf    d0,@2            ; and loop.
  1398.  
  1399.  
  1400. ; ============================
  1401. ; Ready now to do the CopyBits
  1402. ; ============================
  1403. PCBSetupCB:
  1404.     move.l    scratchCicn(a4),a1    ; get handle to cicn
  1405.     move.l    (a1),-(sp)        ; push pointer to src bits
  1406.     
  1407.     pea    curPort(a4)
  1408.     _GetPort
  1409.     move.l    curPort(a4),a1        ; get pointer to port
  1410.     lea    2(a1), a1        ; pointer to port's bitmap
  1411.     move.l    a1, -(sp)
  1412.     
  1413.     move.l    scratchCicn(a4),a1    ; get handle to cicn
  1414.     move.l    (a1),a1            ; get pointer to cicn
  1415.     lea    6(a1), a1        ; pointer to bounds rect
  1416.     move.l    a1,-(sp)
  1417.  
  1418.     move.l    parm_rectptr(a6),-(sp)    ; dest rect pointer
  1419.  
  1420.     move    #36, -(sp)        ; push mode (transparent)
  1421.     clr.l    -(sp)            ; no mask
  1422.     _CopyBits
  1423.  
  1424. PCBGiveUp:
  1425. PCBExit:
  1426.  
  1427.     RESTORE_ALL
  1428.     STACK_END
  1429.  
  1430. whiteRGB    dc.w $ffff, $ffff, $ffff
  1431. blackRGB    dc.w 0, 0, 0
  1432. grayRGB        dc.w $8000, $8000, $8000
  1433.  
  1434.  
  1435. ; end of IconPatch.asm
  1436.  
  1437.